package fr.jade.fraclite.orb.io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.jgroups.blocks.RpcDispatcher;
import org.jgroups.util.Util;

import fr.jade.fraclite.orb.api.Binder;


/**
 * 
 * @author <a href="mailto:florent.metral@inrialpes.fr">Florent Metral
 *
 */
public class FHAMarshaller implements RpcDispatcher.Marshaller {
        static final byte NULL  = 0;
        static final byte BOOL  = 1;
        static final byte LONG  = 2;
        static final byte OBJ   = 3;

        protected Binder binder;
        
        public FHAMarshaller(Binder binder){
          this.binder = binder;
        }
        public byte[] objectToByteBuffer(Object obj) throws Exception {
            ByteArrayOutputStream out=new ByteArrayOutputStream(24);
            //ObjectOutputStream oos=new ObjectOutputStream(out);
            ObjectOutputStream oos=new RmiObjectOutputStream(out, binder);

            try {
                if(obj == null) {
                    oos.writeByte(NULL);
                }
                else if(obj instanceof Boolean) {
                    oos.writeByte(BOOL);
                    oos.writeBoolean(((Boolean)obj).booleanValue());
                }
                else if(obj instanceof Long) {
                    oos.writeByte(LONG);
                    oos.writeLong(((Long)obj).longValue());
                }
                else {
                    oos.writeByte(OBJ);
                    oos.writeObject(obj);
                }
                oos.flush();
                return out.toByteArray();
            }
            finally {
                Util.close(oos);
            }
        }

        public Object objectFromByteBuffer(byte[] buf) throws Exception {
            ByteArrayInputStream inp=new ByteArrayInputStream(buf);
            //ObjectInputStream in=new ObjectInputStream(inp);
            ObjectInputStream in=new RmiObjectInputStream(inp, binder);

            try {
                int type=in.readByte();
                switch(type) {
                    case NULL:
                        return null;
                    case BOOL:
                        return new Boolean(in.readBoolean());
                    case LONG:
                        return new Long(in.readLong());
                    case OBJ:
                        return in.readObject();
                    default:
                        throw new IllegalArgumentException("incorrect type " + type);
                }
            }
            finally {
                Util.close(in);
            }
        }
    }

